/**
 * setTimeout and setInterval based on requestAnimationFrame api
 * useage:
 * RafTimer.setTimeout(function(t) {
 *   console.log('setTimeout', JSON.stringify(t));
 * });
 * RafTimer.setInterval(function(t) {
 *   console.log('setInterval', JSON.stringify(t));
 *   if (t.count > 3) t.quit();
 * }, 500);
 */
export default class RafTimer {
  constructor(callback, interval = 1000, once = true) {
    this.callback = callback
    this.interval = interval
    this.once = once
    this.count = 0
    this.ts = 0
  }

  run() {
    this.rafId = window.requestAnimationFrame((ts) => {
      this.start ??= ts
      if (!this.stop) {
        if (ts - this.start > this.interval * (this.count + 1)) {
          this.ts = ts
          this.count++
          this.callback(this)
          if (!this.once) this.run()
        } else {
          this.run()
        }
      }
    })
    return this
  }

  quit() {
    cancelAnimationFrame(this.rafId)
    this.stop = true
  }

  static setTimeout(callback, interval = 1000) {
    return new RafTimer(callback, interval, true).run()
  }

  static setInterval(callback, interval = 1000) {
    return new RafTimer(callback, interval, false).run()
  }
}
